using Engine;
using Game;
using GameEntitySystem;
using TemplatesDatabase;

namespace SCIENEW {
    /// <summary>
    /// 机器行为的类，与NormalBlockBehavior相对接
    /// </summary>
    public class SubsystemNormalBlockBehavior : SubsystemPollableBlockBehavior, IUpdateable {
        public override int[] HandledBlocks => [BaseNormalBlock.Index];

        public Dictionary<string, NormalBlockBehavior[]> behaviorsMap = new();

        public UpdateOrder UpdateOrder => UpdateOrder.Default;

        public override void Load(ValuesDictionary valuesDictionary) {
            base.Load(valuesDictionary);
            foreach (var deviceData in NormalBlockManager.IdMap) {
                NormalBlock normalBlock = NormalBlockManager.GetNormalBlock(deviceData.Key);
                behaviorsMap.Add(deviceData.Key, normalBlock.GetBehaviors(Project));
            }
        }

        public override void OnBlockAdded(int value, int oldValue, int x, int y, int z) {
            string normalBlockID = NormalBlockManager.GetNormalBlock(value).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    behavior.OnBlockAdded(value, oldValue, x, y, z);
                }
            }
        }

        public override void OnBlockRemoved(int value, int newValue, int x, int y, int z) {
            string normalBlockID = NormalBlockManager.GetNormalBlock(value).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    behavior.OnBlockRemoved(value, newValue, x, y, z);
                }
            }
        }

        public override bool OnInteract(TerrainRaycastResult raycastResult, ComponentMiner componentMiner) {
            string normalBlockID = NormalBlockManager.GetNormalBlock(raycastResult.Value).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    return behavior.OnInteract(raycastResult, componentMiner);
                }
            }
            return false;
        }

        public override bool OnUse(Ray3 ray, ComponentMiner componentMiner) {
            string normalBlockID = NormalBlockManager.GetNormalBlock(componentMiner.ActiveBlockValue).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    return behavior.OnUse(ray, componentMiner);
                }
            }
            return false;
        }

        public override void OnBlockGenerated(int value, int x, int y, int z, bool isLoaded) {
            string normalBlockID = NormalBlockManager.GetNormalBlock(value).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    behavior.OnBlockGenerated(value, x, y, z, isLoaded);
                }
            }
        }

        public override void OnBlockModified(int value, int oldValue, int x, int y, int z) {
            string normalBlockID = NormalBlockManager.GetNormalBlock(value).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    behavior.OnBlockModified(value, oldValue, x, y, z);
                }
            }
        }

        public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ) {
            int blockValue = SubsystemTerrain.Terrain.GetCellValueFast(x, y, z);
            string normalBlockID = NormalBlockManager.GetNormalBlock(blockValue).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    behavior.OnNeighborBlockChanged(
                        x,
                        y,
                        z,
                        neighborX,
                        neighborY,
                        neighborZ
                    );
                }
            }
        }

        public override void OnHitByProjectile(CellFace cellFace, WorldItem worldItem) {
            int blockValue = SubsystemTerrain.Terrain.GetCellValueFast(cellFace.X, cellFace.Y, cellFace.Z);
            string normalBlockID = NormalBlockManager.GetNormalBlock(blockValue).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    behavior.OnHitByProjectile(cellFace, worldItem);
                }
            }
        }

        public override void OnCollide(CellFace cellFace, float velocity, ComponentBody componentBody) {
            int blockValue = SubsystemTerrain.Terrain.GetCellValueFast(cellFace.X, cellFace.Y, cellFace.Z);
            string normalBlockID = NormalBlockManager.GetNormalBlock(blockValue).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    behavior.OnCollide(cellFace, velocity, componentBody);
                }
            }
        }

        public override void OnPoll(int value, int x, int y, int z, int pollPass) {
            int blockValue = SubsystemTerrain.Terrain.GetCellValueFast(x, y, z);
            string normalBlockID = NormalBlockManager.GetNormalBlock(blockValue).GetCraftingId(); //获取方块值所对应的设备实例
            NormalBlockBehavior[] behaviors = behaviorsMap[normalBlockID];
            if (behaviors.Length > 0) {
                foreach (var behavior in behaviors) {
                    behavior.OnPoll(value, x, y, z, pollPass);
                }
            }
        }

        public void Update(float dt) {
            foreach (var behaviors in behaviorsMap) {
                if (behaviors.Value.Length <= 0) continue;
                foreach (var behavior in behaviors.Value) {
                    if (behavior is IUpdateable updateable) {
                        updateable.Update(dt);
                    }
                }
            }
        }
    }
}